<?php 

//安全过滤
function daddslashes($string) {
    $ra = Array('/script/','/javascript/','/vbscript/','/expression/','/applet/','/meta/','/xml/','/blink/','/link/','/style/','/embed/','/object/','/frame/','/layer/','/bgsound/','/base/','/onload/','/onunload/','/onchange/','/onsubmit/','/onreset/','/onselect/','/onblur/','/onfocus/','/onabort/','/onkeydown/','/onkeypress/','/onkeyup/','/onclick/','/ondblclick/','/onmousedown/','/onmousemove/','/onmouseout/','/onmouseover/','/onmouseup/','/onunload/');
    
    if (is_array($string)) {
        foreach ($string as $key => $value) {
            if (!is_array($value)) {
                // 检查 magic_quotes_gpc 配置的状态
                if (!ini_get('magic_quotes_gpc')) {
                    $value = addslashes($value);
                }
                
                // 使用 stripslashes 处理 magic_quotes_gpc 转义过的字符
                $value = stripslashes($value);

                // 删除非打印字符，粗暴式过滤 XSS 可疑字符串
                $value = preg_replace($ra, '', $value);

                // 去除 HTML 和 PHP 标记并转换为 HTML 实体
                $string[$key] = htmlentities(strip_tags($value));
            } else {
                // 递归调用
                $string[$key] = daddslashes($value);
            }
        }
    }

    return $string;
}
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
	$ckey_length = 4;
	//$key = md5($key ? $key : ENCRYPT_KEY);
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);
	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);
	$result = '';
	$box = range(0, 255);
	$rndkey = array();
	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}
	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}
	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}
	if($operation == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	} else {
		return $keyc.str_replace('=', '', base64_encode($result));
	}
}
//生成随机数字
function randpw($len=8,$format='ALL'){
    $is_abc = $is_numer = 0;
    $password = $tmp ='';
    switch($format){
        case 'ALL':
            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        break;
        case 'CHAR':
            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        break;
        case 'NUMBER':
            $chars='0123456789';
        break;
        default :
            $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        break;
    }
    mt_srand((double)microtime()*1000000*getmypid());
    while(strlen($password)<$len){
        $tmp =substr($chars,(mt_rand()%strlen($chars)),1);
        if(($is_numer <> 1 && is_numeric($tmp) && $tmp > 0 )|| $format == 'CHAR'){
            $is_numer = 1;
        }
        if(($is_abc <> 1 && preg_match('/[a-zA-Z]/',$tmp)) || $format == 'NUMBER'){
            $is_abc = 1;
        }
        $password.= $tmp;
    }
    if($is_numer <> 1 || $is_abc <> 1 || empty($password) ){
        $password = randpw($len,$format);
    }
    return $password;
}
/**
 * 发送 POST JSON 数据的通用函数
 * 
 * @param string $url 请求的 URL
 * @param array $data 要发送的 JSON 数据
 * @param array $headers 自定义头信息 (key => value 格式)
 * @return array 返回响应数据和状态
 */
function postJson_curl($url, $data, $headers = []) {
    // 初始化 cURL
    $ch = curl_init($url);

    // 默认头信息
    $defaultHeaders = [
        'Content-Type: application/json',
        'Accept: application/json'
    ];

    // 合并自定义头信息
    foreach ($headers as $key => $value) {
        $defaultHeaders[] = "$key: $value";
    }

    // 配置 cURL 选项
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $defaultHeaders);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    // 执行请求
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    // 检查错误
    if (curl_errno($ch)) {
        $error = curl_error($ch);
        curl_close($ch);
        return [
            'status' => 'error',
            'http_code' => $httpCode,
            'message' => $error
        ];
    }

    // 关闭 cURL
    curl_close($ch);

    // 返回响应
    return [
        'status' => 'success',
        'http_code' => $httpCode,
        'response' => $response // 解码 JSON 响应
    ];
}
//curl  get / post
function get_curl($url,$post=false,$referer=0,$cookie=0,$header=0,$ua=0,$nobaody=0){
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL,$url);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	$httpheader[] = "Accept:*/*";
	$httpheader[] = "Accept-Encoding:gzip,deflate,sdch";
	$httpheader[] = "Accept-Language:zh-CN,zh;q=0.8";
	$httpheader[] = "Connection:close";
	curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
	curl_setopt($ch, CURLOPT_TIMEOUT, 10);
	if($post){
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
	}
	if($header){
		curl_setopt($ch, CURLOPT_HEADER, TRUE);
	}
	if($cookie){
		curl_setopt($ch, CURLOPT_COOKIE, $cookie);
	}
	if($referer){
		if($referer==1){
			curl_setopt($ch, CURLOPT_REFERER, 'http://m.qzone.com/infocenter?g_f=');
		}else{
			curl_setopt($ch, CURLOPT_REFERER, $referer);
		}
	}
	if($ua){
		curl_setopt($ch, CURLOPT_USERAGENT,$ua);
	}else{
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; U; Android 4.4.1; zh-cn; R815T Build/JOP40D) AppleWebKit/533.1 (KHTML, like Gecko)Version/4.0 MQQBrowser/4.5 Mobile Safari/533.1');
	}
	if($nobaody){
		curl_setopt($ch, CURLOPT_NOBODY,1);
	}
	curl_setopt($ch, CURLOPT_ENCODING, "gzip");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
	$ret = curl_exec($ch);
	curl_close($ch);
	return $ret;
}
//获取网络请求数据
function input($method = null) {
    // 初始化数据为空数组
    $data = [];

    switch($method){
        case 'post':
            $data = $_POST ?? [];
            break;
        case 'get':
            $data = $_GET ?? [];
            break;
        case 'input':
            $inputData = file_get_contents('php://input');
            $data = $inputData ? json_decode($inputData, true) : [];
            break;
        case 'cookie':
            $data = $_COOKIE ?? [];
            break;
        case 'session':
            $data = $_SESSION ?? [];
            break;
        default:
            // 合并 POST 和 GET，并确保是数组
            $data = array_merge($_POST ?? [], $_GET ?? []);
            break;
    }
   
    // 确保 $data 是数组，然后再进行过滤
    if (!is_array($data)) {
        $data = [];
    }

    // 递归过滤函数
    $filterValue = function($value) use (&$filterValue) {
        if (is_array($value)) {
            return array_map($filterValue, $value);
        }
        if (is_string($value)) {
            return daddslashes(strip_tags($value));
        }
        // 对于其他类型（数字、布尔等）直接返回
        return $value;
    };

    // 应用过滤
    $filteredData = array_map($filterValue, $data);
    
    return $filteredData;
}
/**
 * 以 JSON 格式输出消息并退出脚本
 * 
 * 此静态函数用于以 JSON 格式输出包含代码和消息的响应信息，并终止脚本执行。可以可选地添加额外的数据到响应中。
 *
 * @param int $code 响应代码
 * @param string $message 响应消息
 * @param array|null $extra 可选的额外数据数组，将与响应合并到一起
 * @return void 无返回值，该函数将以 JSON 格式输出响应并调用 `exit` 终止脚本执行
 */
function exitjson($code, $message, $extra = null) {
    @header('Content-Type: application/json; charset=UTF-8');
    $response = array('code' => $code, 'msg' => $message);
    if ($extra !== null) {
        $response = array_merge($response, $extra);
    }
    exit(json_encode($response));
}

//执行sql操作
function executeSQLQuery($sql, $operation = 'select') {
    global $DB;
    
    try {
        $sql = dealPrefix($sql);
        $stmt = $DB->prepare($sql);
        $stmt->execute();
        if ($operation === 'select') {
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } elseif ($operation === 'delete' || $operation === 'update' || $operation === 'insert') {
            return $stmt->rowCount(); // 返回受影响的行数
        } else {
            return false;
        }
    } catch (PDOException $e) {
        return false;
    }
}
/**
 * 处理SQL表前缀
 * @param string $sql SQL语句
 * @return string
 */
function dealPrefix($sql) {
    return str_replace(sqlPrefix, dbconfig['sqlname'], $sql);
}

/**
 * 执行SQL操作并防范SQL注入
 * @param string $sql SQL语句
 * @param array $params 参数数组
 * @param string $operation 操作类型
 * @param array $options 附加选项
 * @return mixed
 */
function safeSqlQuery($sql, $params = [], $operation = 'select', $options = []) {
    global $DB;
    
    // 默认选项
    $defaultOptions = [
        'fetch_style' => PDO::FETCH_ASSOC,  // 结果集格式
        'single_row' => false,              // 是否只返回单行
        'debug' => false                   // 调试模式
    ];
    
    $options = array_merge($defaultOptions, $options);
    
    try {
        $sql = dealPrefix($sql);
        
        // 缓存处理
        if ($operation === 'select' && $options['cache']) {
            $cacheKey = md5($sql . serialize($params));
            $cached = getCache($cacheKey);
            if ($cached !== false) {
                return $cached;
            }
        }
        
        // 预处理语句
        $stmt = $DB->prepare($sql);
        
        // 智能参数绑定
        foreach ($params as $paramName => &$paramValue) {
            $type = PDO::PARAM_STR;
            if (is_int($paramValue)) {
                $type = PDO::PARAM_INT;
            } elseif (is_bool($paramValue)) {
                $type = PDO::PARAM_BOOL;
            } elseif (is_null($paramValue)) {
                $type = PDO::PARAM_NULL;
            }
            $stmt->bindParam(":$paramName", $paramValue, $type);
        }
        
        // 执行查询
        $stmt->execute();
        
        // 处理结果
        switch (strtolower($operation)) {
            case 'select':
                if ($options['single_row']) {
                    $result = $stmt->fetch($options['fetch_style']);
                    $data = ['result' => $result, 'count' => $result ? 1 : 0];
                } else {
                    $result = $stmt->fetchAll($options['fetch_style']);
                    $data = ['result' => $result, 'count' => count($result)];
                }
                
                // 缓存结果
                if ($options['cache']) {
                    setCache($cacheKey, $data, $options['cache_time']);
                }
                
                return $data;
                
            case 'insert':
                if (!$DB->lastInsertId()) {
                    return $stmt->rowCount();
                }
                return $DB->lastInsertId();
                
            case 'update':
            case 'delete':
                return $stmt->rowCount();
                
            default:
                return false;
        }
        
    } catch (\PDOException $e) {
        if ($options['debug']) {
            throw new \Exception("Database Error: " . $e->getMessage());
        }
        error_log("Database Error: " . $e->getMessage());
        return false;
    }
}
function http_ip(){
    if(getenv('HTTP_CLIENT_IP')){
        $ip = getenv('HTTP_CLIENT_IP');
     }
    elseif(getenv('HTTP_X_FORWARDED_FOR')){
      $ip = getenv('HTTP_X_FORWARDED_FOR');
    }
    elseif(getenv('REMOTE_ADDR')){
      $ip = getenv('REMOTE_ADDR');
    }
    else{
      $ip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
    }
    return $ip;
}

function DeleteHtml($str) 
{ 
    $str = trim($str); //清除字符串两边的空格
    $str = preg_replace("/\t/","",$str); //使用正则表达式替换内容，如：空格，换行，并将替换为空。
    $str = preg_replace("/\r\n/","",$str); 
    $str = preg_replace("/\r/","",$str); 
    $str = preg_replace("/\n/","",$str); 
    $str = preg_replace("/ /","",$str);
    $str = preg_replace("/  /","",$str);  //匹配html中的空格
    return trim($str); //返回字符串
}
function getSubstr($str, $leftStr, $rightStr)
{
    $left = strpos($str, $leftStr);
    //echo '左边:'.$left;
    $right = strpos($str, $rightStr,$left);
    //echo '<br>右边:'.$right;
    if($left < 0 or $right < $left) return '';
    return substr($str, $left + strlen($leftStr), $right-$left-strlen($leftStr));
}

function aes256auth($data,$key,$operation='ENCODE'){//aes 256 加密
    if($operation == 'DECODE'){//解密
        $data = base64_decode($data);
         $decodedData = base64_decode($data);//两次 b64解密
          $iv = substr($decodedData, 0, 16);//取解密后的前16位作为 iv
          $encryptedData = substr($decodedData, 16);//取16位后面的作为解密内容
          $openssl=openssl_decrypt($encryptedData, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);//进行解密
          if($openssl === false){
              return false;
          }
          return base64_decode($openssl);//解密成功 在进行一次 b64解密并返回解密后的字符
    }else{//加密
        $data = base64_encode($data);//对原始数据 b64 加密一次
        $iv = random_bytes(16);//随机生成 16位作为 iv加密字符
        $encryptedData = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);//进行加密
        $encodedData = base64_encode($iv . $encryptedData);//拼接数据  并 b64加密一次
        return base64_encode($encodedData);//在加密一次
    }
}

//检测设备 true  为移动端 false 为pc端
function isMobile(){    
    $useragent=isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';    
    $useragent_commentsblock=preg_match('|\(.*?\)|',$useragent,$matches)>0?$matches[0]:'';      
    function CheckSubstrs($substrs,$text){    
        foreach($substrs as $substr)    
            if(false!==strpos($text,$substr)){    
                return true;    
            }    
            return false;    
    }  
    $mobile_os_list=array('Google Wireless Transcoder','Windows CE','WindowsCE','Symbian','Android','armv6l','armv5','Mobile','CentOS','mowser','AvantGo','Opera Mobi','J2ME/MIDP','Smartphone','Go.Web','Palm','iPAQ');  
    $mobile_token_list=array('Profile/MIDP','Configuration/CLDC-','160×160','176×220','240×240','240×320','320×240','UP.Browser','UP.Link','SymbianOS','PalmOS','PocketPC','SonyEricsson','Nokia','BlackBerry','Vodafone','BenQ','Novarra-Vision','Iris','NetFront','HTC_','Xda_','SAMSUNG-SGH','Wapaka','DoCoMo','iPhone','iPod');    
                
    $found_mobile=CheckSubstrs($mobile_os_list,$useragent_commentsblock) ||    
              CheckSubstrs($mobile_token_list,$useragent);    
                
    if ($found_mobile){    
        return true;    
    }else{    
        return false;    
    }    
}
//短信发信
function send_sms($phone,$code,$scope='reg'){
    global $conf;
    switch ($conf['sms_api']){
        case '1':
            if($scope=='reg'){
                 $templId=$conf['sms_tpl_reg']?$conf['sms_tpl_reg']:$conf['sms_tpl_univer'];
            }else if($scope == 'find'){
                 $templId=$conf['sms_tpl_find']?$conf['sms_tpl_find']:$conf['sms_tpl_univer'];
            }else if($scope == 'edit'){
                $templId=$conf['sms_tpl_modify']?$conf['sms_tpl_modify']:$conf['sms_tpl_univer'];
            }else if($scope == 'regsucc'){
                $json=json_decode($code,true);
                $templId=$conf['sms_tpl_phonesuccid'];
            }else if($scope == 'auth'){
                $templId=$conf['sms_tpl_phoneauth']?$conf['sms_tpl_phoneauth']:$conf['sms_tpl_univer'];
            }else if($scope == 'univer'){
                $templId = $conf['sms_tpl_univer'];
            }
            if (!empty($conf['sms_appid']) && !empty($conf['sms_appkey']) && !empty($conf['sms_sign']) && !empty($templId)) {
                 $tencentSms = new \lib\sms\TencentSms($conf['sms_appid'], $conf['sms_appkey']);
                 if($scope == 'regsucc'){
                      $params=array($json['user'],$json['pwd']);
                      
                 }else{
                      $params=array($code,'5'); 
                 }
                 $result = $tencentSms->sendWithParam("86", $phone, $templId, $params, $conf['sms_sign']);
                 if(!empty($result)){
                     $json=json_decode($result,true);
                     if($json['result']==0){
                         $arr=array("code"=>200,"msg"=>"腾讯云测试发信成功");
                     }else{
                         $arr=array("code"=>-1,"msg"=>"短信发送失败:".$json['errmsg']);
                     }
                 }else{
                     $arr=array("code"=>-1,"msg"=> "发送请求失败，请检查网络或接口配置");
                 }
            }else{
                $arr=array("code"=>-1,"msg"=> "缺少必要的参数，请确保配置了 appid、appkey、签名 和 短信模板");
            }
            return json_encode($arr);
          break;
         case '2': 
             if($scope=='reg'){
                  $template=$conf['ali_sms_regid']?$conf['ali_sms_regid']:$conf['ali_sms_univer'];
                }elseif($scope=='find'){
                   $template=$conf['ali_sms_find']?$conf['ali_sms_find']:$conf['ali_sms_univer'];
                }else if($scope=='edit'){
                   $template=$conf['ali_sms_modify']?$conf['ali_sms_modify']:$conf['ali_sms_univer'];  
                }else if($scope == 'univer'){
                    $template=$conf['ali_sms_univer'];  
                }
             if(!empty($conf['ali_sms_akid']) && !empty($conf['ali_sms_aks']) && !empty($conf['ali_sms_qm']) && !empty($template)){
                   $aliyunSMS = new \lib\sms\Aliyun($conf['ali_sms_akid'], $conf['ali_sms_aks']);
                  $result = $aliyunSMS->send($phone, $code, $template, $conf['ali_sms_qm']);
                  if(isset($result['Code']) && $result['Code'] == "OK"){
                      $arr=array("code"=>200,"msg"=>"阿里云测试发信成功");
                  }else{
                    $arr=array("code"=>-1,"msg"=>isset($result['Message']) ? $result['Message'] : '未知错误');  
                  }
             }else{
                   $arr=array("code"=>-1,"msg"=> "缺少必要的参数，请确保配置了 appid、appkey、签名 和 短信模板");
             }
            return json_encode($arr);
         break;
         case '3':
             if($scope=='reg'){//注册
                $content = "【".$conf['smsbao_qm']."】您正在进行手机注册,您的验证码为：".$code."，该验证码在5分钟内有效，如非本人操作请忽略";
            }else if($scope=='find'){//找回
                $content ="【".$conf['smsbao_qm']."】您正在申请找回密码，您的验证码为：".$code."，该验证码在5分钟内有效，如非本人操作请忽略，并及时修改密码避免被盗";
            }else if($scope=='regsucc'){//注册成功通知
                $json=json_decode($code,true);
                 $content ="【".$conf['smsbao_qm']."】恭喜您注册成功！您的注册平台账号为：".$json['user']."，您的平台密码为：".$json['pwd']."，请牢记您的账号和密码并妥善保管，避免被盗！";
            }else if($scope == 'edit'){//修改密码
                $content ="【".$conf['smsbao_qm']."】您正在操作修改密码，您的验证码为：".$code."，该验证码在5分钟内有效，如非本人操作请忽略，并及时修改密码避免被盗";
            }else if($scope == 'univer'){
                $content ="【".$conf['smsbao_qm']."】您的验证码是：".$code."，该验证码在5分钟内有效，如非本人操作请忽略，并及时修改密码避免被盗";
            }
             if(!empty($conf['smsbao_user']) && !empty($conf['smsbao_key']) && !empty($conf['smsbao_qm'])){
                 $smsbao=json_decode(sms_bao($conf['smsbao_user'],$conf['smsbao_key'],$phone,$content),true);
                 if($smsbao['code']==0){
                      $arr=array("code"=>200,"msg"=>"短信宝测试发信成功");
                 }else{
                     $arr=array("code"=>$smsbao['code'],"msg"=>isset($smsbao['msg']) ? $smsbao['msg'] : '未知错误');  
                 }
             }else{
                   $arr=array("code"=>-1,"msg"=>"缺少必要的参数，请确保配置了 短信宝账号、短信宝key、签名 ");  
             }
             return json_encode($arr);
         break;   
          
    }
}
//短信宝 对接
function sms_bao($user,$pass,$phone,$content){
    $statusStr = array(
        "0" => "短信发送成功",
        "-1" => "参数不全",
        "-2" => "服务器空间不支持,请确认支持curl或者fsocket，联系您的空间商解决或者更换空间！",
        "30" => "密码错误",
        "40" => "账号不存在",
        "41" => "余额不足",
        "42" => "帐户已过期",
        "43" => "IP地址限制",
        "50" => "内容含有敏感词"
    );
   $smsapi = "http://api.smsbao.com/";
   $sendurl = $smsapi."sms?u=".$user."&p=".$pass."&m=".$phone."&c=".urlencode($content);
   $result=get_curl($sendurl);
   return json_encode(array("code"=>$result,"msg"=>$statusStr[$result]));
}
//php发信邮件
function send_mail($to, $sub, $msg) {
	global $conf;
	if(!$conf['mail_name'] || !$conf['mail_port'] || !$conf['mail_smtp'] || !$conf['mail_pwd'])return false;
	$port = intval($conf['mail_port']);
	$mail = new \lib\mail\PHPMailer\PHPMailer(true);
	try{
		$mail->SMTPDebug = 0;
		$mail->CharSet = 'UTF-8';
		$mail->Timeout = 5;
		$mail->isSMTP();
		$mail->Host = $conf['mail_smtp'];
		$mail->SMTPAuth = true;
		$mail->Username = $conf['mail_name'];
		$mail->Password = $conf['mail_pwd'];
		if($port == 587) $mail->SMTPSecure = 'tls';
		else if($port >= 465) $mail->SMTPSecure = 'ssl';
		else $mail->SMTPAutoTLS = false;
		$mail->Port = intval($conf['mail_port']);
		$mail->setFrom($conf['mail_name'], $conf['sitename']);
		$mail->addAddress($to);
		$mail->addReplyTo($conf['mail_name'], $conf['sitename']);
		$mail->isHTML(true);
		$mail->Subject = $sub;
		$mail->Body = $msg;
		$mail->send();
		return true;
	} catch (Exception $e) {
		return $mail->ErrorInfo;
	}
}
function createLog($type, $ip , $uid = "admin") {
    global $DB; 
   
    // 参数验证和重排序
    if (func_num_args() < 3) {
        $ip = $type;
        $type = $uid;
        $uid = "admin";
    }

    // 参数清理
    $uid = trim($uid);
    $ip = trim($ip);
    $type = trim($type);

    // 空值检查
    if (empty($type) || empty($ip)) {
        return false;
    }

    // 准备 SQL 语句
    $sql = "INSERT INTO `".dbconfig['sqlname']."log` (`name`, `ip`, `logtxt`, `time`) VALUES (:name, :ip, :logtxt, NOW())";
    
    try {
        // 准备并执行 SQL 查询
        $stmt = $DB->prepare($sql);
        $stmt->bindValue(':name', $uid, PDO::PARAM_STR);
        $stmt->bindValue(':ip', $ip, PDO::PARAM_STR);
        $stmt->bindValue(':logtxt', $type, PDO::PARAM_STR);
        
        $result = $stmt->execute();

        // 错误处理
        if (!$result) {
            if(debug)error_log('Log creation failed: ' . print_r($stmt->errorInfo(), true));
            return false;
        }

        return true;
    } catch (PDOException $e) {
        if(debug)error_log('PDO Exception in createLog: ' . $e->getMessage());
        return false;
    } catch (Exception $e) {
        if(debug)error_log('Unexpected error in createLog: ' . $e->getMessage());
        return false;
    }
}
function adminhost(){
    $requestUri = $_SERVER['REQUEST_URI'];
    $uri = parse_url($requestUri, PHP_URL_PATH);
    $uri = ltrim($uri, '/');
    $parts = explode('/', $uri); // 解析 URI
    if(count($parts) == 1):
            $parts[1] = 'index';
            $uri = implode('/', $parts);
            header("Location: ".$uri);
    endif;
}
function Wx_protocol($xf_type){
    if (in_array($xf_type, ['1', '7', '8','9','10'])) {
        return 'lib\\protocol\\WxMac';  // 使用完整的命名空间路径
    } else if(in_array($xf_type, ['3', '4', '5','6'])){
        return 'lib\\protocol\\WxUos';
    } else if(in_array($xf_type, ['11', '12', '13'])){
        return 'lib\\protocol\\WxIpad';
    }else{
        return null;
    }
}
function xfhttp_post_yun($url, $Header, $data=NULL){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $Header);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POST, 1); // 发送一个常规的Post请求
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // Post提交的数据包
    curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
    curl_setopt($ch, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    $sResult = curl_exec($ch);
    if($sError=curl_error($ch)){
        die($sError);
    }
    curl_close($ch);
    return $sResult;
}

function Wx_jixin($xf_type){
    if (in_array($xf_type, ['1', '7', '8','9','10'])) {
        return 'Mac';  // 使用完整的命名空间路径
    } else if(in_array($xf_type, ['3', '4', '5','6'])){
        return 'Uos';
    } else if(in_array($xf_type, ['11', '12', '13'])){
        return 'Ipad';
    }else{
        return null;
    }
}
function maskSensitiveInfo($phone = NULL, $email = NULL) {
    $maskedPhone = $phone;
    $maskedEmail = $email;

    // 检查手机号是否不为空且长度符合标准手机号长度
    if (!empty($phone) && strlen($phone) == 11) {
        $maskedPhone = substr($phone, 0, 3) . str_repeat('*', 4) . substr($phone, -4);
    }

    // 检查邮箱是否不为空且包含@
    if (!empty($email) && strpos($email, '@') !== false) {
        $parts = explode('@', $email);
        $localPart = $parts[0];
        $domainPart = $parts[1];

        // 保留邮箱用户名的第一个和最后一个字符，中间用*替代
        if (strlen($localPart) > 1) {
            $maskedEmail = substr($localPart, 0, 1) . str_repeat('*', max(0, strlen($localPart) - 2)) . substr($localPart, -1) . '@' . $domainPart;
        }
    }

    return array($maskedPhone, $maskedEmail);
}

function test_mask($data = []) {
    $arr = [];
    foreach ($data as $pwd){
        // 获取密码长度
        $length = strlen($pwd);
        $arr[] = str_repeat('*', $length);
    }
    
    // 生成相同长度的星号字符串
    return $arr;
}

function getdomain($url){//获取域名
	$arr=parse_url($url);
	return $arr['host'];
}

function download_zip($zip_name,$zip_url)
{
    ob_start(); //打开输出
    readfile($zip_url); //输出图片文件
    $zip = ob_get_contents(); //得到浏览器输出
  
    ob_end_clean(); //清除输出并关闭
    file_put_contents($zip_name, $zip);
	mkdir('../'.dirname(__FILE__).$zip_name, 0777);
	@chmod('../'.dirname(__FILE__).$zip_name, 0777);
    return $zip_name;
}
function zipExtract($src, $dest)
{
  $zip = new ZipArchive();
  if ($zip->open($src) === true) {
    $zip->extractTo($dest);
    $zip->close();
    return true;
  }
  return false;
}
function get_zip_originalsize($filename, $path) {
  //先判断待解压的文件是否存在
  if(!file_exists($filename)){
   exit(json_encode(array("code"=>-1,"msg"=>"文件".$filename."不存在")));
  }
  $starttime = explode(' ',microtime()); //解压开始的时间

  //将文件名和路径转成windows系统默认的gb2312编码，否则将会读取不到
  $filename = iconv("utf-8","gb2312",$filename);
  $path = iconv("utf-8","gb2312",$path);
  //打开压缩包
  $resource = zip_open($filename);
  $i = 1;
  //遍历读取压缩包里面的一个个文件
  while ($dir_resource = zip_read($resource)) {
    //如果能打开则继续
    if (zip_entry_open($resource,$dir_resource)) {
      //获取当前项目的名称,即压缩包里面当前对应的文件名
      $file_name = $path.zip_entry_name($dir_resource);
      //以最后一个“/”分割,再用字符串截取出路径部分
      $file_path = substr($file_name,0,strrpos($file_name, "/"));
      //如果路径不存在，则创建一个目录，true表示可以创建多级目录
      if(!is_dir($file_path)){
        mkdir($file_path,0777,true);
      }
      //如果不是目录，则写入文件
      if(!is_dir($file_name)){
        //读取这个文件
        $file_size = zip_entry_filesize($dir_resource);
        //最大读取6M，如果文件过大，跳过解压，继续下一个
        if($file_size<(1024*1024*30)){
          $file_content = zip_entry_read($dir_resource,$file_size);
          file_put_contents($file_name,$file_content);
        }else{
          return $i++." 此文件已被跳过，原因：文件过大， -> ".iconv("gb2312","utf-8",$file_name);
        }
      }
      //关闭当前
      zip_entry_close($dir_resource);
    }
  }
  //关闭压缩包
  zip_close($resource);
  $endtime = explode(' ',microtime()); //解压结束的时间
  $thistime = $endtime[0]+$endtime[1]-($starttime[0]+$starttime[1]);
  $thistime = round($thistime,3); //保留3为小数
  return "解压完毕！，本次解压花费：$thistime 秒。";
}
?>